/**
 * 
 */

#include "flash_if.h"
#include "bsp_uart.h"
#include <stdio.h>

/**
 * @brief 初始化 Flash 接口
 * 
 * 解锁 Flash 并清除相关标志位。
 */
void FLASH_If_Init(void)
{
    // 解锁
    FLASH_Unlock();

    // 清除标志位
    FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPRTERR | FLASH_FLAG_PGERR);
}


/**
 * @brief 返回用户闪存区域的写保护状态。
 * 
 * @return uint32_t 
 */
uint32_t FALSH_If_GetWriteProtectionStatus(void)
{
    return (~FLASH_GetWriteProtectionOptionByte() & FLASH_PROTECTED_PAGES);
}


/**
 * @brief 禁用用户闪存区域的写保护。
 * 
 * @return uint8_t 0: 成功, 1: 失败, 2: 已经禁用
 */
uint8_t FALSH_If_DisableWriteProtection(void)
{
    uint32_t user_menory_mask = 0, WRPR = 0;
    FLASH_Status status = FLASH_BUSY;

    /* 清除 flash 标志位*/
    FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPRTERR | FLASH_FLAG_PGERR);

    /* 获取用户闪存区域的写保护状态 */
    WRPR = FLASH_GetWriteProtectionOptionByte();

    /* 测试用户闪存区域是否写入保护 */
    if (FALSH_If_GetWriteProtectionStatus() != 0)
    {
        /* 解除对FLASH_CR寄存器的访问限制 */
        FLASH_Unlock();

        /* 擦除选项字节 */
        status = FLASH_EraseOptionBytes();

        user_menory_mask = FLASH_PROTECTED_PAGES | WRPR;

        if (user_menory_mask != 0xFFFFFFFF)
        {
            /* 禁用用户闪存区域的写保护 */
            status = FLASH_EnableWriteProtection((uint32_t)~user_menory_mask);
        }
        if (status == FLASH_COMPLETE)
        {
            printf("\r\nWrite Protection is disabled.\r\n");
            return 0;
        }
        else
        {
            printf("\r\nWrite Protection disable failed.\r\n");
            return 1;
        }
    }
    else
    {
        printf("\r\nWrite Protection is already disabled.\r\n");
        return 2;
    }
}

/**
 * @brief 擦除指定的 Flash 扇区
 * 
 * @param start_sector 起始扇区地址
 * @return uint32_t 0: 成功, 1: 错误
 */
uint32_t FLASH_If_Erase(uint32_t start_sector)
{
    uint32_t flash_address = start_sector;

    while (flash_address < USER_FLASH_LAST_PAGE_ADDRESS)
    {
        if (FLASH_ErasePage(flash_address) == FLASH_COMPLETE)
        {
            flash_address += FLASH_PAGE_SIZE; // Move to the next page
        }
        else
        {
            return 1; // Error occurred
        }
    }

    return 0; // Erase completed successfully
}

/**
 * @brief 将数据写入 Flash
 * 
 * @param flash_address Flash 地址
 * @param data 数据缓冲区
 * @param data_length 数据长度
 * @return uint32_t 0: 成功, 1: 错误, 2: 验证失败
 */
uint32_t FLASH_If_Write(__IO uint32_t* flash_address, uint32_t* data, uint16_t data_length)
{
    for (uint32_t i = 0; (i < data_length) && (*flash_address < USER_FLASH_END_ADDRESS - 4); i++)
    {
        if (FLASH_ProgramWord(*flash_address, data[i]) == FLASH_COMPLETE)
        {
            if (*(uint32_t*)*flash_address != data[i])
            {
                return 2; // Verification failed
            }
            *flash_address += 4; // Move to the next word
        }
        else
        {
            return 1; // Error occurred during programming
        }
    }
    return 0; // Write completed successfully
}
